/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package net.etrs.formathlon.metier.utils.pdf;

import com.itextpdf.text.Document;
import com.itextpdf.text.PageSize;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfContentByte;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.List;
import java.util.Properties;
import net.etrs.formathlon.entity.formation.Participation;
import net.etrs.formathlon.entity.formation.Seance;
import net.etrs.formathlon.entity.utilisateur.Personnel;
import net.etrs.formathlon.entity.utilisateur.Utilisateur;
import net.etrs.formathlon.metier.exception.MetierException;
import net.etrs.formathlon.metier.utils.DateUtils;

/**
 * Classe qui va s'occuper des différents exports pdf.
 * @author OPIF
 */
public class PDFManager {
    

    // Support de création du document
    private static PdfContentByte canvas;
    // Police de base
    private static BaseFont bf;
    // Taille par défaut de la police
    private static final int DEFAULT_SIZE=13;
    // Taille par défaut d'un interligne
    private static final int DEFAULT_INTERLIGNE=3;
    // Taille par défaut des marges
    private static final int DEFAULT_MARGIN=10;
    

    /**
     * Génère un fichier PDF d'attestation de participation.
     * Il concerne un utilisateur et liste les formations auxquelles il a participé.
     * @param utilisateur L'utilisateur concerné par l'attestation.
     * @param prop Le fichier de configuration.
     * @param dateDebut Date d'affectation de la personne.
     * @param dateFin Date de fin d'affectation de la personne.
     * @return Le lien vers le fichier PDF généré.
     * @throws MetierException 
     */
    public static String generateAttestation(Utilisateur utilisateur, Properties prop, Date dateDebut, Date dateFin) throws MetierException {
        
        if(utilisateur.getPersonnel()==null){
            throw new MetierException(MetierException.Type.USER_SANS_PERSONNEL);
        }
        
        Personnel personne=utilisateur.getPersonnel();
        
        try{
            synchronized(PDFManager.class){
                // Chargement des configs
                String source=prop.getProperty("application.pdf.attestation.source");
                String dest=prop.getProperty("application.pdf.attestation.destination");
                
                // Chargement du fichier de base
                PdfReader reader = new PdfReader(source);
                // Création du document de travail
                Document document = new Document();
                // Sauvegarde du fichier de destination basé sur le document
                PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(dest));
                // Ouverture du document
                document.open();
                // Récupération du canevas (calque unique)
                canvas = writer.getDirectContent();
                // On récupère la première page du fichier de base
                PdfImportedPage page = writer.getImportedPage(reader, 1);
                // On ajoute cette page dans le canevas en tant que template
                canvas.addTemplate(page, 0, 0);

                // Création d'une police
                bf = BaseFont.createFont(BaseFont.TIMES_ROMAN, "", BaseFont.EMBEDDED);

                
                //TRAITEMENT DE L'ATTESTATION
                {
                    // PREPARATION DES DONNEES
                    String nom = personne.toString();
                    String fonction=String.format(
                            prop.getProperty("application.pdf.attestation.detail.fonction"),
                            utilisateur.getEntite());
                    String debut=String.format("du %s",DateUtils.getDateFormatee(dateDebut));
                    String fin=String.format("au %s",DateUtils.getDateFormatee(dateFin));
                    String signature1=String.format(
                            prop.getProperty("application.pdf.attestation.signature.ligne1"),
                            DateUtils.getDateFormatee(new Date()));
                    String signature2=prop.getProperty("application.pdf.attestation.signature.ligne2");
                    String signature3=prop.getProperty("application.pdf.attestation.signature.ligne3");
                    
                    //nom de la personne
                    addChunk(nom, 116, 500, 16);
                    //fonction de la personne
                    addChunk(fonction, 40, 473);
                    //date de début de la période de formation
                    addChunk(debut, 40, 444);
                    //date de fin de la période de formation
                    addChunk(fin, 150, 444);
                    //liste des formations
                    int i=0;
                    for(Participation participation : personne.getParcoursPeda()){
                        //inititulé de la formation
                        addChunk(participation.getFormation().getLibelle(), 66, 386-i);
                        //date de la participation
                        addChunk(DateUtils.getDateFormatee(participation.getDateFormation()), 424, 386-i);
                        i+=DEFAULT_SIZE+DEFAULT_INTERLIGNE;
                    }
                    //signature
                    addChunk(signature1, 350, 130+DEFAULT_SIZE+DEFAULT_INTERLIGNE);
                    addChunk(signature2, 350, 130);
                    addChunk(signature3, 350, 130-DEFAULT_SIZE-DEFAULT_INTERLIGNE);
                }


                // Fermeture du document
                document.close();

                // Retourne le chemin du fichier généré.
                return dest;
            }
        }
        catch(Exception ex){
            throw new MetierException(MetierException.Type.PDF_ATTESTATION_ERREUR_TECHNIQUE, ex);
        }
        
    }


    /**
     * Ajouter une phrase à une position absolue dans la page.
     * @param message La phrase à écrire.
     * @param x La position x absolue.
     * @param y La position y absolue.
     */
    private static void addChunk(String message, int x, int y){
        addChunk(message, x, y, DEFAULT_SIZE);
    }


    /**
     * Ajouter une phrase à une position absolue dans la page.
     * @param message La phrase à écrire.
     * @param x La position x absolue.
     * @param y La position y absolue.
     * @param size La taille de la police.
     */
    private static void addChunk(String message, int x, int y, int size){
        canvas.beginText();
        canvas.setTextMatrix(x, y);
        canvas.setFontAndSize(bf, size);
        canvas.showText(message);
        canvas.endText();
    }

    
    /**
     * Génère un fichier d'émargement pour une session.
     * @param detail Le détail affiché sous le titre.
     * @param listSeance La liste des séances dans les colonnes.
     * @param listPersonnel La liste des personnes dans les lignes
     * @param prop Le fichier de config.
     * @return Le lien vers le fichier PDF généré.
     */
    public static String generateEmargement(String detail,
                                            List<Seance> listSeance,
                                            List<Personnel> listPersonnel,
                                            Properties prop) throws MetierException {
        try{
            // Chargement des configs
            String dest=prop.getProperty("application.pdf.emargement.destination");
            String titre=prop.getProperty("application.pdf.emargement.titre");
            int nbSeancesParPage=Integer.parseInt(prop.getProperty("application.pdf.emargement.seancesparpage"));
            
            
            // Création du document
            Document document = new Document(PageSize.A4.rotate());
            PdfWriter.getInstance(document, new FileOutputStream(dest));
            
            // Ouverture du flux
            document.open();
            
            // Titre
            document.add(new Paragraph(titre));
            document.add(new Paragraph(detail));
            
            // Insertion des données par page
            for(int noPage=0; noPage*nbSeancesParPage<listSeance.size();noPage++){
                document.add(createTableEmargement(listSeance, listPersonnel,noPage,nbSeancesParPage));
            }
            
            // Fermeture du flux
            document.close();
            
            return dest;
        }
        catch(Exception ex){
            throw new MetierException(MetierException.Type.PDF_EMARGEMENT_ERREUR_TECHNIQUE, ex);
        }
    }
    
    
    
    /**
     * Création du tableau d'émargement d'une session.
     * @param listSeance La liste des séances sur les colonnes.
     * @param listInscription La liste des inscriptions pour connaitres les personnes à mettre
     * dans les lignes.
     * @param noPage No de la page à générer.
     * @param nbSeancesParPage Nombre de séances à insérer dans le tableau.
     * @return Le tableau au format PDF.
     */
    private static PdfPTable createTableEmargement(List<Seance> listSeance, List<Personnel> listPersonnel, int noPage, int nbSeancesParPage) {
        
        int nbSeances=nbSeancesParPage;
        // si on est sur la dernière page, on risque de faire un "Array index out of range" sur listSeance
        if((noPage+1)*nbSeancesParPage>listSeance.size()){
            //dans ce cas, n'afficher que le modulo
            nbSeances=listSeance.size()%nbSeancesParPage;
        }
        
        //Création d'une table. Nombre de colonnes déterminé par le nombre de séances.
        PdfPTable table = new PdfPTable(nbSeances+1);
        table.setSpacingBefore(DEFAULT_SIZE);
        
        PdfPCell cell;
        //Entete
        cell = new PdfPCell(new Phrase("Personnels"));
        table.addCell(cell);
        for(int i=noPage*nbSeances;i<(noPage+1)*nbSeances;i++){
            Seance seance=listSeance.get(i);
            cell = new PdfPCell(new Phrase(String.format("%s (%sh)",
                    DateUtils.getDateHeureFormatee(seance.getDateHeureDebut()),
                    seance.getDuree())));
            table.addCell(cell);
        }
        
        //remplissage du tableau
        for(Personnel personnel : listPersonnel){
            //Nom de la personne
            cell = new PdfPCell(new Phrase(personnel.toString()));
            table.addCell(cell);
            for(int i=noPage*nbSeances;i<(noPage+1)*nbSeances;i++){
                //case vide pour chaque seance
                cell = new PdfPCell(new Phrase(""));
                table.addCell(cell);
            }
        }
        
        return table;
    }
    
}